// WS2803_test
// By Thomas Olson
// teo20130202.01
// WS2803 18 channel LED driver
// Arduino 5V 16Mhz
// WS2803 pin4 CKI - > ws2803_clockPin
// WS2803 pin5 SDI - > ws2803_dataPin
// WS2803 pin2 IREF = Rext to GND.
// WS2803 pin6-23 = OUT0-17

// According to the documentation...
// WS2803 will receive 144 bits(18 bytes), latching it to itself
// and then relay further bits to the next WS2803.
//
// But in fact, if you send more than 18 bytes say 36, then the
// first 18 bytes are passed on to the second WS2803. And the next 18 bytes
// are displayed in the first WS2803. And this is the behavior that is indicated
// in timing chart (Fig 4.) of the documentation.
//
// This test code assumes two WS2803 in the chained together.
// We will see that the second WS2803 displays the 1st-18th bytes sent and
// the first WS2803 will display the 19th-36th bytes.
// So...
// The byte order is 0-17. The bit order is MSB-LSB. The chip order is Last to First.

const int ws2803_clockPin = 7;
const int ws2803_dataPin = 8;
int led = 9;           // the pin that the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

#define nLEDs 18

uint8_t ledBar[nLEDs]; // Array representing LED PWM levels (byte size)

void setup() {
 
  pinMode(ws2803_clockPin, OUTPUT);
  pinMode(ws2803_dataPin, OUTPUT);
  pinMode(led, OUTPUT);

// Initialize WS2803 - Clock needs to be low at least 600us to prepare itself.
  digitalWrite(ws2803_clockPin, LOW);
  delayMicroseconds(600);

// Initialize the ledBar array - all LEDs OFF.
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[18] = 0x00;
  }
  loadWS2803();
}

void loop() {  
  for (int i = 0; i < 255; i++) {
    ledBar[0] = i;
    fadePWMPin();
    loadWS2803();
    delay(1);
  }
  
  for (int i = 255; i > 0; i--) {
    ledBar[0] = i;
    loadWS2803();
    fadePWMPin();
    delay(1);
  }
  
  

//
//// Simple test - LED Chaser
//
//  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
//    ledBar[wsOut] = 0x3C; // 23% brightness
//    loadWS2803();
//
//    delay(100);  // ON time for each LED during chase.
//
//    ledBar[wsOut] = 0x00; // Full OFF
//    loadWS2803();
//  }

//  delay(1000);

/*  
// Simple test - increase brightness to max and then dim to min each LED
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    for(int iOut = 0; iOut < 256; iOut++){ // brighten one LED
      ledBar[wsOut] = iOut;
      loadWS2803();
    }
    for(int iOut = 0; iOut < 256; iOut++){ // now dim that one LED
      ledBar[wsOut] = (uint8_t)0xFF & 255-iOut;
      loadWS2803();
    }
  }

  delay(1000);
*/

} //loop

void fadePWMPin() {
  analogWrite(led, brightness);    

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade: 
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ; 
  }     
}

void loadWS2803(){
    for (int wsOut = 0; wsOut < nLEDs; wsOut++){
    shiftOut(ws2803_dataPin, ws2803_clockPin, MSBFIRST, ledBar[wsOut]);
    }
    delayMicroseconds(600); // 600us needed to reset WS2803s
}


